package minidb.buffer; 

public class BufferPool {
	private Buffer[] bufferpool;
	private java.util.HashMap<Integer, Buffer> usedBuffer;
	private java.util.ArrayList<Buffer> freeBuffer;
	private byte[] lock = new byte[0];
	
	public BufferPool(int numbuffs) {
		bufferpool = new Buffer[numbuffs];
		usedBuffer = new java.util.HashMap<Integer, Buffer>();
		freeBuffer = new java.util.ArrayList<Buffer>();
		for (int i=0; i<numbuffs; i++){
			bufferpool[i] = new Buffer(0);
			freeBuffer.add(bufferpool[i]);
		}

		
	}
	
	public void flushAll() {
		synchronized(lock){
			for (Buffer buff : bufferpool){
				if (buff.isModifiedBy()){
					buff.flush();
				}
			}
		}
	}
	
	public  Buffer pin(int pageNum){
		Buffer buf;
		synchronized(lock){
			if((buf = usedBuffer.get(new Integer(pageNum)))== null){
				if(freeBuffer.size()==0)
					return null;
				buf = freeBuffer.remove(0);
				if(buf.isModifiedBy())
					flushAll();
				if(usedBuffer.containsValue(buf))
					usedBuffer.remove(new Integer(buf.pageNum()));
				buf.pageNum(pageNum);
				buf.pin();
				usedBuffer.put(new Integer(pageNum), buf);
				return buf;
			}
			else{
				if(!buf.ispin())
					freeBuffer.remove(buf);
				buf.pin();			
				return buf;
			}
		}
	}
	
	public void unpin(Buffer buf){
		buf.unpin();
		if(!buf.ispin()){
			synchronized(lock){
				if(!freeBuffer.contains(buf)){
					freeBuffer.add(buf);
				}
			}
		}
	}
	
	
}
